#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "pikascript.h"
#include "driver/usb_serial_jtag.h"
#include "esp_vfs_dev.h"
#include "sdkconfig.h"
#include "sd_fatfs.h"
#include "driver/gpio.h"

char pika_platform_getchar()
{
    while (1)
    {
        char buff[1] = {0};
        if (usb_serial_jtag_read_bytes(buff, 1, portMAX_DELAY) > 0)
        {
            return buff[0];
        }
        return buff[1];
    }
}

int pika_platform_putchar(char ch)
{
    usb_serial_jtag_write_bytes(&ch, 1, portMAX_DELAY);
    return 0;
}

FILE *pika_platform_fopen(const char *filename, const char *modes)
{
    return fopen(filename, modes);
}

int pika_platform_fclose(FILE *fp) { return fclose(fp); }

int pika_platform_fseek(FILE *fp, long offset, int whence)
{
    return fseek(fp, offset, whence);
}

long pika_platform_ftell(FILE *fp) { return ftell(fp); }

size_t pika_platform_fread(void *ptr, size_t size, size_t count, FILE *fp)
{
    return fread(ptr, size, count, fp);
}

size_t pika_platform_fwrite(const void *ptr, size_t size, size_t count,
                            FILE *fp)
{
    return fwrite(ptr, size, count, fp);
}

void pika_platform_reboot(void)
{
    // esp_restart();
    abort();
}

/*IO 操作*/
#define BOOT_GPIO_PIN GPIO_NUM_0
#define BOOT gpio_get_level(BOOT_GPIO_PIN)

/**
 * @brief 初始化按键
 * @param 无
 * @retval 无
 */
void key_init(void)
{
    gpio_config_t gpio_init_struct;
    gpio_init_struct.intr_type = GPIO_INTR_DISABLE;        /* 失能引脚中断 */
    gpio_init_struct.mode = GPIO_MODE_INPUT;               /* 输入模式 */
    gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE;      /* 使能上拉 */
    gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; /* 失能下拉 */
    gpio_init_struct.pin_bit_mask = 1ull << BOOT_GPIO_PIN; /* BOOT 按键引脚 */
    gpio_config(&gpio_init_struct);                        /* 配置使能 */
}

void eriase_task(void *pvParameters)
{
    while (1)
    {
        if (BOOT == 0)
        {
            vTaskDelay(10 / portTICK_PERIOD_MS); /* 去抖动 */
            if (BOOT == 0)
            {
                // 擦除
                printf("remove");
                remove(PIKA_SHELL_SAVE_APP_PATH);
                esp_restart();
            }
        }
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    TaskHandle_t task_handle;
    printf("Hello world!\n");
    usb_serial_jtag_driver_config_t usb_serial_jtag_config = {
        .rx_buffer_size = 1024 * 8,
        .tx_buffer_size = 1024};
    usb_serial_jtag_driver_install(&usb_serial_jtag_config);
    // esp虚拟文件系统
    esp_vfs_usb_serial_jtag_use_driver();
    key_init();
    sd_fatfs_init();

    // 必须使用宏PRIu32,否则putchar会卡死，不工作。
    uint32_t a = 5;
    printf("Minimum free heap size: %" PRIu32 " bytes\n", a);
    // PikaObj* pikaMain = pikaScriptInit();
    // pikaScriptShell(pikaMain);
    // 创建动态任务
    xTaskCreate(eriase_task, "Dynamic Task", 2048, (void *)5, 5, &task_handle);
    vTaskDelay(3000 / portTICK_PERIOD_MS);

    PikaObj *root = NULL;
    FILE *fp = fopen(PIKA_SHELL_SAVE_APP_PATH, "rb");
    if (fp != NULL)
    {
        fclose(fp);
        printf("[Info] load app from sd card\n");
        root = newRootObj("pikaMain", New_PikaMain);
        obj_linkLibraryFile(root, PIKA_SHELL_SAVE_APP_PATH);
        obj_runModule(root, "main");
    }
    else
    {
        printf("[Info] load app from firmware\n");
        root = pikaPythonInit();
    }
    pikaScriptShell(root);

    while (1)
    {

        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
}
